﻿/*
 * Copyright 2007-2008  Lukasz Laszko lukaszlaszko@gmail.com
 * 
 * Permission to use, copy, modify, and distribute this software
 * and its documentation for any purpose and without fee is hereby
 * granted, provided that the above copyright notice appear in all
 * copies and that both that the copyright notice and this
 * permission notice and warranty disclaimer appear in supporting
 * documentation, and that the name of the author not be used in
 * advertising or publicity pertaining to distribution of the
 * software without specific, written prior permission.
 * 
 * The author disclaim all warranties with regard to this
 * software, including all implied warranties of merchantability
 * and fitness.  In no event shall the author be liable for any
 * special, indirect or consequential damages or any damages
 * whatsoever resulting from loss of use, data or profits, whether
 * in an action of contract, negligence or other tortious action,
 * arising out of or in connection with the use or performance of
 * this software. 
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Reflection;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;

namespace Pg.BioMedics.SDR.Web.Controls
{
    /// <summary>
    /// Advanced file upload control supporting operation in hosted view.
    /// </summary>
    [ToolboxData("<{0}:FileUpload runat=\"server\"><{0}:FileUpload/>")]
    [ToolboxItem(true)]
    [ValidationProperty("UploadedFileName")]
    public class FileUpload : WebControl
    {
        #region Constants

        private const string FileUploadScript = "Pg.BioMedics.SDR.Web.Controls.FileUpload.FileUpload.js";
        private const string UploadIdViewStateKey = "UploadId";

        #endregion

        #region Fields

        private string uploadFrameId = Guid.NewGuid().ToString();
        private string clientOnUploadStarted;
        private string clientOnUploadProgress;
        private string clientOnUploadCompleted;
        private string clientOnError;

        #endregion

        #region Properties

        /// <summary>
        /// Gets / sets client script handler code for upload start event
        /// </summary>
        public string ClientOnUploadStarted
        {
            get
            {
                return this.clientOnUploadStarted;
            }

            set
            {
                this.clientOnUploadStarted = value;
            }
        }

        /// <summary>
        /// Gets / sets client script handler code for upload progress changed event
        /// </summary>
        public string ClientOnUploadProgress
        {
            get
            {
                return this.clientOnUploadProgress;
            }

            set
            {
                this.clientOnUploadProgress = value;
            }
        }

        /// <summary>
        /// Gets / sets client script handler code for upload compleated event
        /// </summary>
        public string ClientOnUploadCompleted
        {
            get
            {
                return this.clientOnUploadCompleted;
            }

            set
            {
                this.clientOnUploadCompleted = value;
            }
        }

        /// <summary>
        /// Gets / sets client error handler
        /// </summary>
        public string ClientOnError
        {
            get
            {
                return this.clientOnError;
            }

            set
            {
                this.clientOnError = value;
            }
        }

        /// <summary>
        /// Gets file uploaded by this control
        /// </summary>
        public UploadedFile UploadedFile
        {
            get
            {
                return UploadedFilesRegister.Instance[GetUploadId()];
            }
        }

        /// <summary>
        /// Gets name of uploaded file
        /// </summary>
        public string UploadedFileName
        {
            get
            {
                if (UploadedFile != null)
                    return UploadedFile.FileName;
                else
                    return null;
            }
        }

        #endregion

        #region Methods

        /// <summary>
        /// Remove temporarly uploaded file
        /// </summary>
        public void Clean()
        {
            UploadedFilesRegister.Instance.Unregister(GetUploadId());
        }

        #endregion

        #region Overriden methods

        protected override void CreateChildControls()
        {
            // load scripts
            ScriptManagerProxy scriptManagerProxy = new ScriptManagerProxy();
            scriptManagerProxy.Scripts.Add(new ScriptReference(FileUploadScript, Assembly.GetExecutingAssembly().FullName));
            Controls.Add(scriptManagerProxy);
           
            // create iframe
            Literal iframe = new Literal();
            iframe.Text = String.Format("<iframe id=\"{0}\" scrolling=\"no\" height=\"40px\" frameborder=\"0\" src=\"{1}?uploadId={2}\" class=\"{3}\"></iframe>", this.uploadFrameId, 
                                                                                                                                                  FileUploadModule.UploadFormPath,
                                                                                                                                                  GetUploadId(),
                                                                                                                                                  CssClass);
            Controls.Add(iframe);

            // register startup and submit scripts
            ScriptManager.RegisterStartupScript(this, typeof(Page), Guid.NewGuid().ToString(), BuildStartupScript(), true);
            //ScriptManager.RegisterOnSubmitStatement(this, typeof(Page), Guid.NewGuid().ToString(), BuildSubmitScript());
        }

        #endregion

        #region Support methods

        private string BuildStartupScript()
        {
            StringBuilder startupScript = new StringBuilder();
            startupScript.AppendFormat("FileUpload.updatePanelId = '{0}';", GetUpdatePanelId());
            if (!String.IsNullOrEmpty(this.clientOnUploadStarted))
                startupScript.AppendLine("FileUpload.onUploadStarted = function() { {0} };".Replace("{0}", this.clientOnUploadStarted));
            if (!String.IsNullOrEmpty(this.clientOnUploadProgress))
                startupScript.AppendLine("FileUpload.onUploadProgress = function(status) { {0} };".Replace("{0}", this.clientOnUploadProgress));
            if (!String.IsNullOrEmpty(this.clientOnUploadCompleted))
                startupScript.AppendLine("FileUpload.onUploadCompleted = function(status) { {0} };".Replace("{0}", this.clientOnUploadCompleted));

            return startupScript.ToString();
        }

        private string BuildSubmitScript()
        {
            StringBuilder submitScript = new StringBuilder();
            submitScript.AppendFormat("FileUpload.uploadFile('{0}');", this.uploadFrameId);

            return submitScript.ToString();
        }

        private Guid GetUploadId()
        {
            if (ViewState[UploadIdViewStateKey] == null)
                ViewState[UploadIdViewStateKey] = Guid.NewGuid();

            return (Guid)ViewState[UploadIdViewStateKey];
        }

        private string GetUpdatePanelId()
        {
            Control host = Parent;
            while (host != null)
            {
                if (host.GetType() == typeof(UpdatePanel))
                    return host.ClientID.Replace('_', '$');
                else
                    host = host.Parent;
            }

            return null;

        }

        #endregion
    }
}
